<?php


namespace App\Service\api;


use App\Common\RedisUtils;
use App\Common\Res;
use App\Common\SendTalkMsgUtils;
use App\Common\StringUtils;
use App\Constants\ConstCode;
use App\Constants\ErrorCode;
use App\Model\form\AttachmentTrait;
use App\Model\form\MessageTalkTrait;
use App\Model\form\UserDeviceTrait;
use App\Model\form\WeworkAccountTrait;
use App\Model\form\WeworkFriendTrait;
use App\Model\FriendTalk;
use App\Model\MessageTalk;
use App\Request\api\MessageRequest;
use Hyperf\DbConnection\Db;
use Hyperf\Utils\ApplicationContext;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Hyperf\Config\Annotation\Value;

class messageService
{
    use StringUtils, Res, RedisUtils,
        SendTalkMsgUtils, WeworkAccountTrait,
        AttachmentTrait, MessageTalkTrait, WeworkFriendTrait, UserDeviceTrait;

    /**
     * @Value("commonset.hostUrl")
     */
    protected $hostUrl;

    /**
     * @Value("commonset.webHostUrl")
     */
    protected $webHostUrl;


    /**
     * 获取客服未读消息条数
     * @param array $params
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getOperationReadableCount($fd): array
    {
        $server = $this->checkChatToken(ConstCode::CHAT_TOKEN . $fd);
        if (empty($server)) {
            return $this->Error(ErrorCode::ERROR, '客服登录失效');
        }
        $data['commandType'] = ConstCode::COMMAND_TYPE_NINETEEN;
        $data['contents'] = [];
        try {
            $where = function ($query) use ($server) {
                $query->where('status', ConstCode::IS_USE);
                $query->where('user_id', $server['id']);
            };
            $result = $this->getWeworkAccountList($where);
            $list = [];
            if (!empty($result)) {
                foreach ($result as $key => $value) {
                    $list[$key]['marketUserId'] = $value['marketUserId'];
                    if (!empty($value['marketUserId'])) {
                        $map = function ($query) use ($value) {
                            $query->where('marketUserId', $value['marketUserId']);
                            $query->where('readable', 0);
                            $query->where('direction', 1);
                            $query->where('is_send', ConstCode::IS_SEND);
                        };
                        $list[$key]['readableCount'] = $this->getMessageTalkCount($map);
                    } else {
                        $list[$key]['readableCount'] = 0;
                    }
                }
            }
            $data['contents'] = $list;
            $this->sendMessageTalk($fd, $data);
            return $this->Success('账号未读数量获取成功');
        } catch (\Throwable $ex) {
            $result = $this->sendMessageTalk($fd, $data);
            return $this->Error(ErrorCode::ERROR, '账号发送消息获取失败' . $ex->getMessage());
        }
    }

    /**
     * 获取对话列表
     * @param array $params
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getAllFriendTalkList($fd, array $params): array
    {
        ApplicationContext::getContainer()->get(MessageRequest::class)->validated($params, 'getAllFriendTalkList');
        Db::beginTransaction();
        try {
            $server = $this->checkChatToken(ConstCode::CHAT_TOKEN . $fd);
            if (empty($server)) {
                return $this->Error(ErrorCode::ERROR, '客服登录失效');
            }
            $accountIdArr = $this->getWeworkAccountIdArr(['user_id' => $server['id'], 'status' => ConstCode::IS_USE]);
            if (empty($accountIdArr)) {
                return $this->Error(ErrorCode::ERROR, '账号为空');
            }
            $where = function ($query) use ($accountIdArr) {
                $query->whereIn('account_id', $accountIdArr);
            };
            $list = [];
            $query = FriendTalk::where($where);
            $count = $query->count();
            $pageNum = !empty($params['pageNum']) ? intval($params['pageNum']) : 0;
            $result = $query->offset($params['pageNum'] * $params['pageSize'])
                ->limit($params['pageSize'])->orderByDesc('id')->get()->toArray();
            if (!empty($result)) {
                foreach ($result as $key => $value) {
                    $map_friend = function ($query) use ($value) {
                        $query->where('userId', $value['userId']);
                    };
                    $friend = $this->getWeworkFriend($map_friend);
                    $map = function ($query) use ($value) {
                        $query->where('id', $value['account_id']);
                    };
                    $account = $this->getWeworkAccount($map);
                    $list[$key]['marketAvatar'] = !empty($account['avatar']) ? $this->hostUrl . $account['avatar'] : '';
                    $list[$key]['marketNickName'] = $account['account_name'];
                    $list[$key]['marketUserId'] = $account['marketUserId'];
                    $list[$key]['marketMobileNo'] = $account['mobile'];
                    $list[$key]['marketSex'] = $account['sex'];

                    $lastOneMessage = $this->getLastOneMessage(['userId' => $value['userId'], 'account_id' => $value['account_id'], 'is_send' => ConstCode::IS_SEND]);
                    $list[$key]['lastMsgType'] = !empty($lastOneMessage) ? $lastOneMessage['type'] : 0;
                    $list[$key]['lastMsg'] = !empty($lastOneMessage) ? $lastOneMessage['content'] : '';

                    $list[$key]['readableCount'] = $this->getMessageTalkCount(['account_id' => $value['account_id'], 'userId' => $value['userId'], 'readable' => 0, 'direction' => 1, 'is_send' => ConstCode::IS_SEND]);
                    $list[$key]['status'] = $value['status'];
                    $list[$key]['marketUserType'] = 0;

                    $list[$key]['remark'] = !empty($friend) ? $friend['remark'] : '';
                    $list[$key]['isRoomMsg'] = false;
                    $list[$key]['userSex'] = $value['userSex'];
                    $list[$key]['timestamp'] = strtotime($value['created_at']) * 1000;
                    $list[$key]['userAvatar'] = !empty($friend['path']) ? $this->hostUrl . $friend['path'] : '';
                    $list[$key]['userId'] = $value['userId'];
                    $list[$key]['userNickName'] = !empty($friend['nickname']) ? $friend['nickname'] : $friend['bookname'];
                    $list[$key]['uerMobileNo'] = !empty($friend['mobile']) ? $friend['mobile'] : '';
                }
            }
            $data['total'] = $count;
            $data['totalPages'] = ceil($count / $params['pageSize']);
            $data['traceNo'] = trim($params['traceNo']);
            $data['commandType'] = ConstCode::COMMAND_TYPE_FIFTEEN;
            $data['currentPage'] = $pageNum;
            $data['contents'] = $list;
            $result = $this->sendMessageTalk($fd, $data);
            Db::commit();
            return $this->Success('获取对话列表成功', $result);
        } catch (\Throwable $ex) {
            Db::rollBack();
            $data['code'] = ErrorCode::ERROR;
            $data['msg'] = $ex->getMessage();
            $result = $this->sendMessageTalk($fd, $data);
            return $this->Error(ErrorCode::ERROR, '获取对话列表失败' . $ex->getMessage());
        }
    }


    /**
     * 获取单个账号对话列表成功
     * @param array $params
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getFriendTalkList($fd, array $params): array
    {
        ApplicationContext::getContainer()->get(MessageRequest::class)->validated($params, 'getFriendTalkList');
        Db::beginTransaction();
        try {
            $where = function ($query) use ($params) {
                $query->where('marketUserId', $params['marketUserId']);
            };
            $list = [];
            $account = $this->getWeworkAccount($where);
            $query = FriendTalk::where(['account_id' => $account['id']]);
            $count = $query->count();
            $pageNum = !empty($params['pageNum']) ? intval($params['pageNum']) : 0;
            $result = $query->offset($params['pageNum'] * $params['pageSize'])
                ->limit($params['pageSize'])->orderByDesc('id')->get()->toArray();
            if (!empty($result)) {
                foreach ($result as $key => $value) {
                    $map = function ($query) use ($value) {
                        $query->where('userId', $value['userId']);
                    };
                    $friend = $this->getWeworkFriend($map);
//                    $map = function ($query) use ($value) {
//                        $query->where('id', $value['account_id']);
//                    };
//                    $account = $this->getWeworkAccount($map);
                    $list[$key]['marketAvatar'] = !empty($account['avatar']) ? $this->hostUrl . $account['avatar'] : '';
                    $list[$key]['marketNickName'] = $account['account_name'];
                    $list[$key]['marketUserId'] = $account['marketUserId'];
                    $list[$key]['marketMobileNo'] = $account['mobile'];
                    $list[$key]['marketSex'] = $account['sex'];

                    $lastOneMessage = $this->getLastOneMessage(['userId' => $value['userId'], 'account_id' => $value['account_id'], 'is_send' => ConstCode::IS_SEND]);
                    $list[$key]['lastMsgType'] = !empty($lastOneMessage) ? $lastOneMessage['type'] : 0;
                    $list[$key]['lastMsg'] = !empty($lastOneMessage) ? $lastOneMessage['content'] : '';
                    $list[$key]['readableCount'] = $this->getMessageTalkCount(['account_id' => $value['account_id'], 'userId' => $value['userId'], 'is_send' => 1, 'readable' => 0, 'direction' => 1]);
                    $list[$key]['status'] = 0;
                    $list[$key]['marketUserType'] = 0;

                    $list[$key]['remark'] = !empty($friend) ? $friend['remark'] : '';
                    $list[$key]['isRoomMsg'] = false;
                    $list[$key]['userSex'] = $value['userSex'];
                    $list[$key]['timestamp'] = strtotime($value['created_at']) * 1000;
                    $list[$key]['utype'] = 2;
                    $list[$key]['userAvatar'] = !empty($friend['path']) ? $this->hostUrl . $friend['path'] : '';
                    $list[$key]['userId'] = $value['userId'];
                    $list[$key]['userNickName'] = !empty($friend['nickname']) ? $friend['nickname'] : $friend['bookname'];
                    $list[$key]['uerMobileNo'] = !empty($friend['mobile']) ? $friend['mobile'] : '';
                }
            }
            $data['total'] = $count;
            $data['totalPages'] = ceil($count / $params['pageSize']);
            $data['traceNo'] = trim($params['traceNo']);
            $data['commandType'] = ConstCode::COMMAND_TYPE_THIRTEEN;
            $data['currentPage'] = $pageNum;
            $data['contents'] = $list;
            $result = $this->sendMessageTalk($fd, $data);
            Db::commit();
            return $this->Success('获取单个账号对话列表成功', $result);
        } catch (\Throwable $ex) {
            Db::rollBack();
            $data['code'] = ErrorCode::ERROR;
            $data['msg'] = $ex->getMessage();
            $result = $this->sendMessageTalk($fd, $data);
            return $this->Error(ErrorCode::ERROR, '获取单个账号对话列表失败' . $ex->getMessage());
        }
    }

    /**
     * 获取会话聊天记录
     * @param array $params
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getMessageTalkList($fd, array $params): array
    {
        ApplicationContext::getContainer()->get(MessageRequest::class)->validated($params, 'getMessageTalkList');
        $map = function ($query) use ($params) {
            $query->where('marketUserId', $params['marketUserId']);
        };
        $account = $this->getWeworkAccount($map);
        Db::beginTransaction();
        try {
            $where = function ($query) use ($params, $account) {
                $query->where('account_id', $account['id']);
                $query->where('userId', $params['userId']);
                $query->where('is_send', ConstCode::IS_SEND);
                $query->where('direction', 1);
            };
            $where1 = function ($query) use ($params, $account) {
                $query->where('account_id', $account['id']);
                $query->where('userId', $params['userId']);
                $query->where('direction', 0);
            };
            $list = [];
            $result = $this->getMessageFriendPage($where, $where1, $params);
            if (!empty($result['list'])) {
                foreach ($result['list'] as $key => $value) {
                    $content = $this->getContentByType($value['type'], $value['content']);
                    $list[$key]['content'] = $content;
                    $list[$key]['direction'] = $value['direction'];//1为来源客户 0为来源运营者
                    $list[$key]['readable'] = $value['readable'];
                    $list[$key]['error'] = 0;
                    $list[$key]['marketUserId'] = $this->getWeworkAccountMarketUserId(['id' => $value['account_id']]);
                    $list[$key]['marketUserType'] = 0;
                    $list[$key]['msgType'] = $value['type'];
                    $list[$key]['timestamp'] = intval($value['add_time']);
                    $list[$key]['userAvatar'] = $this->hostUrl . $value['friend']['path'];
                    $list[$key]['userId'] = $value['userId'];
                    $list[$key]['userNickName'] = !empty($value['friend']['nickname']) ? $value['friend']['nickname'] : $value['friend']['bookname'];
                    /*修改状态标记为已读*/
                    if ($value['readable'] == 0) {
                        $this->updateAllUserMessage(['id' => $value['id']], ['readable' => 1]);
                    }
                }
            }
            $data['total'] = $result['count'];
            $data['totalPages'] = ceil($result['count'] / $params['pageSize']);
            $data['commandType'] = ConstCode::COMMAND_TYPE_NINE;
            $data['currentPage'] = $params['pageNum'];
            $data['contents'] = $list;
            $result = $this->sendMessageTalk($fd, $data);
            Db::commit();
            return $this->Success('获取对话记录成功', $result);
        } catch (\Throwable $ex) {
            Db::rollBack();
            $data['code'] = ErrorCode::ERROR;
            $data['msg'] = $ex->getMessage();
            $result = $this->sendMessageTalk($fd, $data);
            return $this->Error(ErrorCode::ERROR, '获取对话记录失败' . $ex->getMessage());
        }
    }


    /**
     * 运营账号发送消息服务端存表
     * @param array $params
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getOperationSendMessage($fd, array $params): array
    {
        ApplicationContext::getContainer()->get(MessageRequest::class)->validated($params, 'getOperationSendMessage');
        Db::beginTransaction();
        try {
            $map = function ($query) use ($params) {
                $query->where('status', ConstCode::IS_USE);
                $query->where('marketUserId', $params['sendId']);
            };
            $account = $this->getWeworkAccount($map);
            $friendWhere = function ($query) use ($params, $account) {
                $query->where('account_id', $account['id']);
                $query->where('userId', $params['receiverId']);
            };
            $friend = $this->getWeworkFriend($friendWhere);
            $add_time = time() * 1000;
            if (!empty($friend) && !empty($account)) {
                $messageId = MessageTalk::insertGetId([
                    'content' => $params['content'],
                    'userId' => $params['receiverId'],
                    'account_id' => $account['id'],
                    'isRoomMsg' => intval($params['isRoomMsg']),
                    'type' => !empty($params['type']) ? $params['type'] : ConstCode::TEXT_TYPE_2,
                    'created_at' => date("Y-m-d H:i:s", time()),
                    'add_time' => $add_time,
                ]);
                /*加入redis用于消息发送*/
                $message['id'] = $messageId;
                $message['content'] = $params['content'];
                $message['userId'] = $params['receiverId'];
                $message['marketUserId'] = $account['marketUserId'];
                $message['direction'] = 0;
                $message['mobile'] = $friend['mobile'];
                $message['bookname'] = $friend['bookname'];
                $message['nickname'] = $friend['nickname'];
                $message['device_id'] = $this->getUserDeviceId(['marketUserId' => $account['marketUserId']]);
                $message['isRoomMsg'] = false;
                $message['operation_user_id'] = $account['user_id'];
                $message['created_at'] = date("Y-m-d H:i:s", time());
                $message['add_time'] = $add_time;
                $message['type'] = !empty($params['type']) ? $params['type'] : ConstCode::TEXT_TYPE_2;
                $message['is_send'] = 0;
                /*判断有没有消息*/
                $messageKey = $this->getMessageKey();
                $message['key'] = $messageKey;
                $res = $this->zAdd('messageKey', intval($add_time), $messageKey);
                if ($res) {
                    $this->hSet('message', $messageKey, json_encode($message, 256));
                }
            }
            Db::commit();
            return $this->Success('运营者发送消息保存成功');
        } catch (\Throwable $ex) {
            Db::rollBack();
            return $this->Error(ErrorCode::ERROR, '运营者发送消息保存失败' . $ex->getMessage());
        }
    }

    /**
     * 运营号发送图片信息
     * @param array $params
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getOperationSendImage($fd, array $params): array
    {
        ApplicationContext::getContainer()->get(MessageRequest::class)->validated($params, 'getOperationSendImage');
        Db::beginTransaction();
        try {
            $map = function ($query) use ($params) {
                $query->where('status', ConstCode::IS_USE);
                $query->where('marketUserId', $params['sendId']);
            };
            $account = $this->getWeworkAccount($map);
            $friendWhere = function ($query) use ($params, $account) {
                $query->where('account_id', $account['id']);
                $query->where('userId', $params['receiverId']);
            };
            $friend = $this->getWeworkFriend($friendWhere);
            $add_time = time() * 1000;
            if (!empty($friend) && !empty($account)) {
                $messageId = MessageTalk::insertGetId([
                    'content' => $params['path'],
                    'userId' => $params['receiverId'],
                    'account_id' => $account['id'],
                    'type' => $params['type'],
                    'isRoomMsg' => intval($params['isRoomMsg']),
                    'created_at' => date("Y-m-d H:i:s", time()),
                    'add_time' => $add_time,
                ]);
                /*加入redis用于消息发送*/
                $message['id'] = $messageId;
                $content = $this->getContentByType($params['type'], $params['path']);
                $message['content'] = $content;
                $message['userId'] = $params['receiverId'];
                $message['device_id'] = $this->getUserDeviceId(['marketUserId' => $account['marketUserId']]);
                $message['marketUserId'] = $account['marketUserId'];
                $message['direction'] = 0;
                $message['mobile'] = $friend['mobile'];
                $message['bookname'] = $friend['bookname'];
                $message['isRoomMsg'] = false;
                $message['operation_user_id'] = $account['user_id'];
                $message['created_at'] = date("Y-m-d H:i:s", time());
                $message['add_time'] = $add_time;
                $message['type'] = $params['type'];
                $message['is_send'] = 0;
                /*判断有没有消息*/
                $messageKey = $this->getMessageKey();
                $message['key'] = $messageKey;
                $res = $this->zAdd('messageKey', intval($add_time), $messageKey);
                if ($res) {
                    $this->hSet('message', $messageKey, json_encode($message, 256));
                }
            }
            Db::commit();
            return $this->Success('运营者发送图片保存成功');
        } catch (\Throwable $ex) {
            Db::rollBack();
            return $this->Error(ErrorCode::ERROR, '运营者发送图片保存失败' . $ex->getMessage());
        }
    }


    /**
     * 产生新对话列表
     * @param array $params
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getNewMessageTalk($fd, array $params): array
    {
        ApplicationContext::getContainer()->get(MessageRequest::class)->validated($params, 'getNewMessageTalk');
        Db::beginTransaction();
        try {
            $data['commandType'] = ConstCode::COMMAND_TYPE_SEVENTEEN;
            $data['traceNo'] = $params['traceNo'];
            $result = $this->sendMessageTalk($fd, $data);
            Db::commit();
            return $this->Success('产生新对话列表');
        } catch (\Throwable $ex) {
            Db::rollBack();
            return $this->Error(ErrorCode::ERROR, '产生新对话列表失败' . $ex->getMessage());
        }
    }


}